strxfrm関数は、ロケール(地域情報)に基づき文字列を変換します。変換は、二つの文字列に対して、それぞれをstrxfrm関数で変換してからstrcmp関数で比較した結果と、strxfrm関数で変換を行わずにstrcoll関数で比較した結果とが同じになるように行います。
また、変換は現在のロケールのLC_COLLATEカテゴリに応じて解釈された文字列に基づいて行われます。ロケールの設定・参照はsetlocale関数で行うことができます。
ロケールがデフォルトの’C’の場合は、strncpy関数で文字列をコピーするのと同じです。
#include <string.h>
size_t strxfrm(char *dest, const char *src, size_t n);
*destは変換結果を設定する文字列を指定します。
*srcは変換対象の文字列を指定します。
nは変換する文字数をバイト単位で指定します。
戻り値として、変換結果の文字列の長さ(ヌル文字は含まない)を返します。もし、戻り値が第3引数のnより大きい場合は、変換は不定です。
次の例題プログラムは、環境変数からロケールを取得して設定しています。
プログラム 例
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <locale.h> /* メンバーの個人情報 */ struct member { int number; /* 番号 */ char name[20]; /* 名前(日本語) */ double height; /* 身長 */ double weight; /* 体重 */ double jump; /* 最高到達点 */ }; /* qsort関数のソートキー比較関数 */ int SortComp(const void *, const void *); int main() { FILE *fp; struct member member_list[20]; struct member *list_ptr; int list_max; int list_cnt; /* ロケールを環境変数から取得して設定 */ if (setlocale(LC_COLLATE, '') == NULL) { fprintf(stderr, 'main : ロケールが設定できませんでした\n'); exit(EXIT_FAILURE); } if ((fp = fopen('beijing_2008_jp.csv', 'r')) == NULL) { fprintf(stderr, 'main : ファイルのオープンに失敗しました\n'); exit(EXIT_FAILURE); } list_ptr = member_list; list_max = 0; /* メンバー情報入力 */ while(fscanf(fp, '%d,%[^,],%lf,%lf,%lf', &list_ptr->number, list_ptr->name, &list_ptr->height, &list_ptr->weight, &list_ptr->jump) != EOF) { ++list_ptr; ++list_max; } fclose(fp); /* member_listを名前をキーにしてソート */ qsort(member_list, list_max, sizeof(struct member), SortComp); list_ptr = member_list; printf('%-4s %-20s %-8s %-8s %s\n', '番号', '名前', '身長', '体重', '最高到達点'); /* ソート後のメンバー情報出力 */ for (list_cnt = 0; list_cnt < list_max; ++list_cnt, ++list_ptr) { printf('%3d %-20s %6.1f %6.1f %6.1f\n', list_ptr->number, list_ptr->name, list_ptr->height, list_ptr->weight, list_ptr->jump); } return EXIT_SUCCESS; } /* qsort関数のソートキー比較関数 */ int SortComp(const void *p1, const void *p2) { struct member *cmp1 = (struct member *)p1; struct member *cmp2 = (struct member *)p2; char name1[20]; char name2[20]; /* strcoll関数で比較したのと同じになるように変換 */ if (strxfrm(name1, cmp1->name, strlen(cmp1->name)) <= strlen(cmp1->name)) { if (strxfrm(name2, cmp2->name, strlen(cmp2->name)) <= strlen(cmp2->name)) { return strcmp(name1, name2); } else { fprintf(stderr, 'SortComp : 名前2の変換に失敗しました\n'); exit(EXIT_FAILURE); } } else { fprintf(stderr, 'SortComp : 名前1の変換に失敗しました\n'); exit(EXIT_FAILURE); } }
例の実行結果
$ cat beijing_2008_jp.csv 1,栗原 ,186,69,305 2,多治見,180,70,309 3,竹下 ,159,52,280 4,大村 ,184,70,319 5,高橋 ,170,65,290 6,佐野 ,159,54,260 7,杉山 ,184,66,310 8,櫻井 ,167,63,290 9,狩野 ,174,65,298 11,荒木 ,186,79,307 12,木村 ,184,66,298 14,河合 ,168,63,280 $ $ ./strxfrm.exe 番号 名前 身長 体重 最高到達点 14 河合 168.0 63.0 280.0 1 栗原 186.0 69.0 305.0 11 荒木 186.0 79.0 307.0 5 高橋 170.0 65.0 290.0 6 佐野 159.0 54.0 260.0 9 狩野 174.0 65.0 298.0 7 杉山 184.0 66.0 310.0 2 多治見 180.0 70.0 309.0 4 大村 184.0 70.0 319.0 3 竹下 159.0 52.0 280.0 12 木村 184.0 66.0 298.0 8 櫻井 167.0 63.0 290.0 $